﻿using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.Drawing;
using SimpleMediaManager.Controls;
using System.Text.RegularExpressions;
using System.Net;

namespace SimpleMediaManager
{
    public partial class BulkAdd : Form
    {
        private const int NumThreads = 5;
        WebClient webclient = new WebClient();
        private List<Movie> addMovies = new List<Movie>();
        private ListViewColumnSorter listviewColumnSorter = new ListViewColumnSorter();
        private bool scanning = false;
        private int threadCount = 0;
        private int completedMatches = 0;
        private int searchPos = 0;
        private int sortedColumn = -1;

        public BulkAdd()
        {
            InitializeComponent();

            typeof(ListView).GetProperty("DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(listViewResults, true, null);

            listViewResults.ListViewItemSorter = listviewColumnSorter;
        }

        private void BulkAdd_Load(object sender, EventArgs e)
        {
            checkBoxFoldersSubdirectories.Checked = Program.Settings.SearchSubDirectories;

            PopulateFolders();

            buttonFoldersScan.Enabled = (CountTotal() > 0);
            buttonFoldersRemove.Enabled = (listViewFolders.SelectedIndices.Count > 0);
            buttonFoldersOpen.Enabled = (listViewFolders.SelectedIndices.Count == 1);
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Delete)
            {
                if (buttonResultsRemove.Enabled && panelResults.Visible && listViewResults.Focused)
                {
                    buttonResultsRemove_Click(null, null);
                }

                return true;
            }

            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void listViewFolders_SelectedIndexChanged(object sender, EventArgs e)
        {
            buttonFoldersRemove.Enabled = (listViewFolders.SelectedIndices.Count > 0);
            buttonFoldersOpen.Enabled = (listViewFolders.SelectedIndices.Count == 1);
        }

        private void buttonFoldersAdd_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.Description = "Select a folder containing movies to be added:";

            if (fbd.ShowDialog() == DialogResult.OK)
            {
                ListViewItem lviFolder = new ListViewItem(fbd.SelectedPath);
                int count = FileCount(fbd.SelectedPath);
                lviFolder.SubItems.Add(MakeStatus(count));
                lviFolder.Tag = count;
                listViewFolders.Items.Add(lviFolder);

                string[] searchFolders = new string[listViewFolders.Items.Count];
                for (int i = 0; i < listViewFolders.Items.Count; i++)
                {
                    searchFolders[i] = listViewFolders.Items[i].Text;
                }

                Program.Settings.SearchDirectories = searchFolders;
                Program.Settings.Serialize(Program.SETTINGS_FILE);

                buttonFoldersScan.Enabled = (CountTotal() > 0);
            }
        }

        private void buttonFoldersRemove_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem selected in listViewFolders.SelectedItems)
            {
                listViewFolders.Items.Remove(selected);
            }

            buttonFoldersScan.Enabled = (CountTotal() > 0);

            string[] searchFolders = new string[listViewFolders.Items.Count];
            for (int i = 0; i < listViewFolders.Items.Count; i++)
            {
                searchFolders[i] = listViewFolders.Items[i].Text;
                i++; // Why?
            }

            Program.Settings.SearchDirectories = searchFolders;
            Program.Settings.Serialize(Program.SETTINGS_FILE);
        }

        private void buttonFoldersOpen_Click(object sender, EventArgs e)
        {
            Process.Start(listViewFolders.SelectedItems[0].Text);
        }

        private void checkBoxFoldersSubdirectories_CheckedChanged(object sender, EventArgs e)
        {
            Program.Settings.SearchSubDirectories = checkBoxFoldersSubdirectories.Checked;
            Program.Settings.Serialize(Program.SETTINGS_FILE);

            PopulateFolders();
            buttonFoldersScan.Enabled = (CountTotal() > 0);
        }

        private void buttonFoldersCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void buttonFoldersScan_Click(object sender, EventArgs e)
        {
            listViewResults.Items.Clear();
            buttonResultsRemove.Enabled = false;
            buttonResultsOpen.Enabled = false;
            buttonResultsEdit.Enabled = false;

            List<Movie> movies = new List<Movie>();
            foreach (ListViewItem lvi in listViewFolders.Items)
            {
                if (Directory.Exists(lvi.Text))
                {
                    string[] files = ListFiles(lvi.Text, checkBoxFoldersSubdirectories.Checked);
                    foreach (string file in files)
                    {
                        Movie movie = Format.GetFileInfo(Path.GetFileNameWithoutExtension(file));

                        foreach (Movie added in movies)
                        {
                            if (added.FileTitle == movie.FileTitle && added.FileYear == movie.FileYear)
                            {
                                added.FileDiscs += 1;
                                movie.FileDiscs += 1;
                                added.Filenames.Add(file);
                            }
                        }

                        if (movie.FileDiscs == 1)
                        {
                            movie.Filenames = new List<string>();
                            movie.Filenames.Add(file);
                            movies.Add(movie);
                        }
                    }
                }
            }

            foreach (Movie movie in movies)
            {
                if (movie.FileTitle != null)
                {
                    ListViewItem lvi = new ListViewItem(new string[] { Path.GetFileName(movie.Filenames[0]), "", "", "Ready", "" });
                    MovieTag movieTag = new MovieTag();
                    movieTag.Search = movie.FileTitle;
                    movieTag.MovieInfo = movie;
                    lvi.Tag = movieTag;
                    listViewResults.Items.Add(lvi);
                }
            }

            progressBarResults.Maximum = listViewResults.Items.Count * 2;
            progressBarResults.Value = 0;
            labelProgress.Text = "0% (0 / " + listViewResults.Items.Count + ")";

            listviewColumnSorter.Sorting = SortOrder.Ascending;
            listviewColumnSorter.Column = 0;
            listViewResults.Sorting = SortOrder.Ascending;
            ListViewColumnSortArrows.SetSortIcons(listViewResults, ref sortedColumn, 0);
            listViewResults.Sort();

            panelFolders.Visible = false;
            panelResults.Visible = true;

            buttonResultsAutoId.Enabled = (listViewResults.Items.Count > 0); //TODO: Only if red
        }

        //---------------------------------------------------------------

        private void listViewResults_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!scanning)
            {
                buttonResultsEdit.Enabled = (listViewResults.SelectedIndices.Count == 1);
                buttonResultsRemove.Enabled = (listViewResults.SelectedIndices.Count > 0);
                buttonResultsOpen.Enabled = (listViewResults.SelectedIndices.Count == 1);
            }
        }

        private void listViewResults_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (listViewResults.SelectedIndices.Count == 1 && !scanning)
            {
                buttonResultsEdit_Click(null, null);
            }
        }

        private void listViewResults_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (!scanning)
            {
                if (e.Column == listviewColumnSorter.Column)
                {
                    listviewColumnSorter.Sorting = (listviewColumnSorter.Sorting == SortOrder.Ascending) ? SortOrder.Descending : SortOrder.Ascending;
                }
                else
                {
                    listviewColumnSorter.Column = e.Column;
                    listviewColumnSorter.Sorting = SortOrder.Ascending;
                }

                listViewResults.Sorting = listviewColumnSorter.Sorting;
                ListViewColumnSortArrows.SetSortIcons(listViewResults, ref sortedColumn, e.Column);

                listViewResults.Sort();
            }
        }

        private void buttonResultsBack_Click(object sender, EventArgs e)
        {
            panelFolders.Visible = true;
            panelResults.Visible = false;

            buttonFoldersOpen.Enabled = false;
            buttonFoldersRemove.Enabled = false;
        }

        private void buttonResultsAutoId_Click(object sender, EventArgs e)
        {
            Program.Tmdb.MovieSearchCompleted += new TMDB.Api.MovieSearchAsyncCompletedEventHandler(tmdb_MovieSearchCompleted);
            Program.Tmdb.GetMovieInfoCompleted += new TMDB.Api.MovieInfoAsyncCompletedEventHandler(Tmdb_GetMovieInfoCompleted);
            scanning = true;
            MovieTag tag;
            searchPos = 0;
            threadCount = 0;
            completedMatches = 0;
            progressBarResults.Value = 0;

            foreach (ListViewItem lvi in listViewResults.Items)
            {
                if (lvi.ForeColor != Color.Green)
                {
                    if (lvi.ForeColor == Color.Red)
                    {
                        lvi.ForeColor = Color.Black;
                    }

                    tag = (MovieTag)lvi.Tag;
                }
            }

            int loops = (NumThreads > listViewResults.Items.Count) ? listViewResults.Items.Count : NumThreads;

            for (int i = 0; i < loops; i++)
            {
                while (listViewResults.Items[searchPos].ForeColor == Color.Green || (listViewResults.Items[searchPos].ForeColor == Color.Red && listViewResults.Items[searchPos].SubItems[3].Text == "Unable to find match"))
                {
                    searchPos += 1;
                    progressBarResults.Value += 1;
                }

                listViewResults.Items[searchPos].SubItems[3].Text = "Scanning...";
                tag = (MovieTag)listViewResults.Items[searchPos].Tag;
                threadCount += 1;
                Program.Tmdb.MovieSearchAsync(tag.Search, searchPos);
                searchPos += 1;
            }

            buttonResultsAbort.Text = "Abort";
            buttonResultsBack.Enabled = false;
            buttonResultsAutoId.Enabled = false;
            buttonResultsEdit.Enabled = false;
            buttonResultsRemove.Enabled = false;
            buttonResultsOpen.Enabled = false;
            buttonResultsAdd.Enabled = false;
        }

        void Tmdb_GetMovieInfoCompleted(object sender, TMDB.MovieInfoCompletedEventArgs e)
        {
            threadCount -= 1;
            MovieTag tag;

            if (scanning)
            {
                if (searchPos < listViewResults.Items.Count)
                {
                    while (listViewResults.Items[searchPos].ForeColor == Color.Purple || (listViewResults.Items[searchPos].ForeColor == Color.Red && listViewResults.Items[searchPos].SubItems[3].Text == "Unable to find match"))
                    {
                        searchPos += 1;
                        progressBarResults.Value += 1;
                        completedMatches += 1;
                    }

                    listViewResults.Items[searchPos].SubItems[3].Text = "Scanning...";
                    tag = (MovieTag)listViewResults.Items[searchPos].Tag;

                    threadCount += 1;

                    EnsureVisibleScroll(searchPos);

                    Program.Tmdb.MovieSearchAsync(tag.Search, searchPos);
                    searchPos += 1;
                }
            }

            if (e.Error == null)
            {
                if (e.Movie != null)
                {
                    completedMatches += 1;

                    MovieTag filetag = (MovieTag)listViewResults.Items[(int)e.UserState].Tag;

                    Movie add = new Movie();
                    add = filetag.MovieInfo;
                    add.Id = e.Movie.Id;
                    add.Title = e.Movie.Name;
                    add.AlternativeTitle = e.Movie.AlternativeName;
                    add.ImdbId = e.Movie.ImdbId;
                    add.Language = e.Movie.Language;
                    add.Overview = e.Movie.Overview;
                    add.Released = e.Movie.Released;
                    add.Trailer = e.Movie.Trailer;
                    add.Votes = e.Movie.Votes;
                    add.Rating = e.Movie.Rating;
                    add.Budget = e.Movie.Budget;
                    add.Certification = e.Movie.Certification;
                    add.Homepage = e.Movie.Homepage;
                    add.Revenue = e.Movie.Revenue;

                    foreach (TMDB.Image img in e.Movie.Images)
                    {
                        if (img.Size == TMDB.ImageSize.original)
                        {
                            add.Cover = img;
                            break;
                        }
                    }

                    addMovies.Add(add);

                    listViewResults.Items[(int)e.UserState].ForeColor = Color.Green;
                    listViewResults.Items[(int)e.UserState].SubItems[3].Text = "Complete";


                }
                else
                {
                    listViewResults.Items[(int)e.UserState].ForeColor = Color.Red;
                    listViewResults.Items[(int)e.UserState].SubItems[3].Text = "Unable to find match";
                }
            }
            else
            {
                listViewResults.Items[(int)e.UserState].ForeColor = Color.Red;
                listViewResults.Items[(int)e.UserState].SubItems[3].Text = "Remote server error";
            }

            progressBarResults.Value += 1;
            int current = progressBarResults.Value;
            int max = progressBarResults.Maximum;
            double percent = ((double)current / (double)max) * 100;

            if (progressBarResults.Value == progressBarResults.Maximum)
            {
                scanning = false;

                percent = 100;
                threadCount = 0;
            }

            labelProgress.Text = percent.ToString("0.0") + "% (" + completedMatches + " / " + listViewResults.Items.Count + ")";

            if (!scanning && threadCount == 0 && percent != 100)
            {
                labelProgress.Text = "Aborted (" + completedMatches + " / " + listViewResults.Items.Count + ")";
                Program.Tmdb.GetMovieInfoCompleted -= new TMDB.Api.MovieInfoAsyncCompletedEventHandler(Tmdb_GetMovieInfoCompleted);
            }
            else if ((scanning && threadCount == 0) || percent == 100)
            {
                buttonResultsAbort.Enabled = true;
                Program.Tmdb.GetMovieInfoCompleted -= new TMDB.Api.MovieInfoAsyncCompletedEventHandler(Tmdb_GetMovieInfoCompleted);
            }

            if (threadCount == 0)
            {
                buttonResultsBack.Enabled = true;
                buttonResultsAutoId.Enabled = true;
                buttonResultsAbort.Text = "Close";

                foreach (ListViewItem lvi in listViewResults.Items)
                {
                    if (lvi.ForeColor == Color.Green)
                    {
                        buttonResultsAdd.Enabled = true;
                        break;
                    }
                }
            }
        }

        private void buttonResultsEdit_Click(object sender, EventArgs e)
        {
            MovieTag tag = (MovieTag)listViewResults.SelectedItems[0].Tag;

            Add form = new Add(true, tag.Search, tag.Results);
            form.ShowDialog();

            if (form.SelectedMovie != null)
            {
                tag.Search = form.SelectedMovie.Name;
                tag.Results = form.SearchResults;
                listViewResults.SelectedItems[0].Tag = tag;

                listViewResults.SelectedItems[0].SubItems[1].Text = form.SelectedMovie.Name;

                if (form.SelectedMovie.Released != null)
                {
                    listViewResults.SelectedItems[0].SubItems[2].Text = form.SelectedMovie.Released.Value.Year.ToString();
                }
                else
                {
                    listViewResults.SelectedItems[0].SubItems[2].Text = "";
                }

                listViewResults.SelectedItems[0].SubItems[3].Text = "Movie manually selected";
                listViewResults.SelectedItems[0].ForeColor = Color.Purple;
            }
        }

        private void buttonResultsRemove_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem selected in listViewResults.SelectedItems)
            {
                listViewResults.Items.Remove(selected);
            }

            progressBarResults.Maximum = listViewResults.Items.Count * 2;
            progressBarResults.Value = 0;
            labelProgress.Text = "0% (0 / " + listViewResults.Items.Count + ")";

            buttonResultsAutoId.Enabled = (listViewResults.Items.Count > 0);
            buttonResultsAdd.Enabled = (listViewResults.Items.Count > 0);
        }

        private void buttonResultsOpen_Click(object sender, EventArgs e)
        {
            MovieTag tag = (MovieTag)listViewResults.SelectedItems[0].Tag;
            Process.Start(tag.MovieInfo.Filenames[0]);
        }

        private void buttonResultsAbort_Click(object sender, EventArgs e)
        {
            if (scanning)
            {
                scanning = false;
                buttonResultsAbort.Text = "Stopping...";

                foreach (ListViewItem lvi in listViewResults.Items)
                {
                    if (lvi.ForeColor == Color.Green)
                    {
                        buttonResultsAdd.Enabled = true;
                        break;
                    }
                }

                foreach (ListViewItem lvi in listViewResults.Items)
                {
                    if (lvi.SubItems[3].Text == "Ready")
                    {
                        lvi.ForeColor = Color.Red;
                        lvi.SubItems[3].Text = "Scan aborted";
                        progressBarResults.Value += 2;
                    }
                }

            }
            else
            {
                this.Close();
            }
        }

        private void buttonResultsAdd_Click(object sender, EventArgs e)
        {
            foreach (Movie movie in addMovies)
            {
                string folder = Program.Settings.MovieDirectory + @"\" + Program.Settings.MovieDirectoryStructure;
                folder = folder.Replace("<title>", movie.Title.Replace(':', '-'));
                folder = folder.Replace("<year>", movie.Released.Value.Year.ToString());

                // Create folder
                if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);

                // Move file
                foreach (string filename in movie.Filenames)
                {
                    if (!File.Exists(folder + @"\" + Path.GetFileName(filename)))
                    {
                        FileInfo file = new FileInfo(filename);
                        if (Program.Settings.MovieCopy)
                        {
                            file.CopyTo(folder + @"\" + Path.GetFileName(filename));
                        }
                        else
                        {
                            file.MoveTo(folder + @"\" + Path.GetFileName(filename));
                        }
                    }
                }

                for (int i = 0; i < movie.Filenames.Count; i++)
                {
                    movie.Filenames[i] = folder + @"\" + Path.GetFileName(movie.Filenames[i]);
                }

                // Download cover
                if (!File.Exists(folder + @"\folder.jpg")) webclient.DownloadFile(movie.Cover.Url, folder + @"\folder.jpg");

                // Add to database
                if (Program.Database.Movies.ContainsKey(movie.Id))
                {
                    Program.Database.Remove(movie.Id);
                }
                Program.Database.Add(movie.Id, movie);
            }

            foreach (ListViewItem lvi in listViewResults.Items)
            {
                MovieTag filetag = (MovieTag)lvi.Tag;
                if (Program.Database.Movies.ContainsKey(filetag.MovieInfo.Id))
                {
                    lvi.Remove();
                }
            }
        }

        //---------------------------------------------------------------

        void tmdb_MovieSearchCompleted(object sender, TMDB.MovieSearchCompletedEventArgs e)
        {
            threadCount -= 1;

            if (e.Error == null)
            {
                if (e.Movies.Length > 0)
                {
                    MovieTag movietag = (MovieTag)listViewResults.Items[(int)e.UserState].Tag;

                    movietag.Results = e.Movies;
                    listViewResults.Items[(int)e.UserState].Tag = movietag;

                    listViewResults.Items[(int)e.UserState].ForeColor = Color.Blue;
                    listViewResults.Items[(int)e.UserState].SubItems[3].Text = "Match found, downloading info...";
                    listViewResults.Items[(int)e.UserState].SubItems[1].Text = e.Movies[0].Name;

                    if (e.Movies[0].Released.HasValue)
                    {
                        listViewResults.Items[(int)e.UserState].SubItems[2].Text = e.Movies[0].Released.Value.Year.ToString();
                    }

                    threadCount += 1;

                    EnsureVisibleScroll((int)e.UserState);

                    Program.Tmdb.GetMovieInfoAsync(e.Movies[0].Id, (int)e.UserState);
                }
                else
                {
                    listViewResults.Items[(int)e.UserState].ForeColor = Color.Red;
                    listViewResults.Items[(int)e.UserState].SubItems[3].Text = "Unable to find match";
                    progressBarResults.Value += 1;

                    if (searchPos < listViewResults.Items.Count)
                    {
                        MovieTag movietag = (MovieTag)listViewResults.Items[searchPos].Tag;
                        threadCount += 1;
                        EnsureVisibleScroll(searchPos);
                        Program.Tmdb.MovieSearchAsync(movietag.Search, searchPos);
                        searchPos += 1;
                    }
                }
            }
            else
            {
                listViewResults.Items[(int)e.UserState].ForeColor = Color.Red;
                listViewResults.Items[(int)e.UserState].SubItems[3].Text = "Remote server error";
                progressBarResults.Value += 1;
            }

            progressBarResults.Value += 1;
            int current = progressBarResults.Value;
            int max = progressBarResults.Maximum;
            double percent = ((double)current / (double)max) * 100;

            if (progressBarResults.Value == progressBarResults.Maximum)
            {
                scanning = false;

                percent = 100;
                threadCount = 0;
            }

            labelProgress.Text = percent.ToString("0.0") + "% (" + completedMatches + " / " + listViewResults.Items.Count + ")";

            if (!scanning && threadCount == 0 && percent != 100)
            {
                labelProgress.Text = "Aborted (" + completedMatches + " / " + listViewResults.Items.Count + ")";
                Program.Tmdb.MovieSearchCompleted -= new TMDB.Api.MovieSearchAsyncCompletedEventHandler(tmdb_MovieSearchCompleted);
            }
            else if ((scanning && threadCount == 0) || percent == 100)
            {
                buttonResultsAbort.Enabled = true;
                Program.Tmdb.MovieSearchCompleted -= new TMDB.Api.MovieSearchAsyncCompletedEventHandler(tmdb_MovieSearchCompleted);
            }

            if (threadCount == 0)
            {
                buttonResultsBack.Enabled = true;
                buttonResultsAutoId.Enabled = true;
                buttonResultsAbort.Text = "Close";

                foreach (ListViewItem lvi in listViewResults.Items)
                {
                    if (lvi.ForeColor == Color.Green)
                    {
                        buttonResultsAdd.Enabled = true;
                        break;
                    }
                }
            }
        }

        //---------------------------------------------------------------

        private void EnsureVisibleScroll(int pos)
        {
            int first = listViewResults.TopItem.Index;
            int h_tot = listViewResults.ClientRectangle.Height - 1;
            int h_hdr = listViewResults.GetItemRect(first).Y; // Height of ColumnHeader, if any
            int h_item = listViewResults.GetItemRect(0).Height; // Height of a single item
            int cntVis = (h_tot - h_hdr) / h_item; // Number of visible items
            int last = Math.Min(listViewResults.Items.Count - 1, first + cntVis); // Index of last (partially) visible item

            if (searchPos <= last && searchPos >= (last - cntVis))
            {
                listViewResults.EnsureVisible(pos);
            }
        }

        private string[] ListFiles(string directory, bool sub)
        {
            List<string> files = new List<string>();

            if (sub)
            {
                string[] dir = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly);

                foreach (string folder in dir)
                {
                    DirectoryInfo dInfo = new DirectoryInfo(folder);
                    FileAttributes attributes = dInfo.Attributes;

                    if (attributes.ToString().IndexOf("ReparsePoint") == -1 && attributes.ToString().IndexOf("System") == -1)
                    {
                        foreach (string file in Directory.GetFiles(folder, "*", SearchOption.AllDirectories))
                        {
                            if (((IList<string>)Program.Settings.SearchFormats).Contains(Path.GetExtension(file)))
                            {
                                files.Add(file);
                            }
                        }
                    }
                }
            }

            foreach (string file in Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly))
            {
                if (((IList<string>)Program.Settings.SearchFormats).Contains(Path.GetExtension(file)))
                {
                    files.Add(file);
                }
            }

            return files.ToArray();
        }

        private int FileCount(string directory)
        {
            return ListFiles(directory, checkBoxFoldersSubdirectories.Checked).Length;
        }

        private string MakeStatus(int count)
        {
            string status = "Found: " + count.ToString();

            if (count == 1)
            {
                status += " video files";
            }
            else
            {
                status += " video files";
            }

            return status;
        }

        private int CountTotal()
        {
            int count = 0;

            foreach (ListViewItem lvi in listViewFolders.Items)
            {
                count += (int)lvi.Tag;
            }

            return count;
        }

        private void PopulateFolders()
        {
            listViewFolders.Items.Clear();

            if (Program.Settings.SearchDirectories != null)
            {
                foreach (string searchFolder in Program.Settings.SearchDirectories)
                {
                    ListViewItem lvi = new ListViewItem(searchFolder);

                    if (Directory.Exists(searchFolder))
                    {
                        lvi.SubItems.Add(MakeStatus(FileCount(searchFolder)));
                    }
                    else
                    {
                        lvi.SubItems.Add("Directory does not exist");
                        lvi.ForeColor = Color.Red;
                    }

                    lvi.Tag = FileCount(lvi.Text);
                    listViewFolders.Items.Add(lvi);
                }
            }
        }

        private void comboBoxMovie_SelectedValueChanged(object sender, EventArgs e)
        {
            Match match = Regex.Match(comboBoxMovie.SelectedItem.ToString(), @"(?<title>.*) \((?<year>\d{4})\)");
            if (match.Success)
            {
                listViewResults.Items[listViewResults.SelectedIndices[0]].SubItems[1].Text = match.Groups["title"].Captures[0].Value;
                if (match.Groups["year"].Captures.Count == 1)
                {
                    listViewResults.Items[listViewResults.SelectedIndices[0]].SubItems[2].Text = match.Groups["year"].Captures[0].Value;
                }
            }
            comboBoxMovie.Visible = false;
        }

        private void comboBoxMovie_Leave(object sender, EventArgs e)
        {
            comboBoxMovie_SelectedValueChanged(null, null);
            listViewResults.Items[listViewResults.SelectedIndices[0]].SubItems[3].Text = "Movie manually selected";
            listViewResults.Items[listViewResults.SelectedIndices[0]].ForeColor = Color.Purple;
        }

        private void listViewResults_MouseUp(object sender, MouseEventArgs e)
        {
            ListViewItem lvi = listViewResults.GetItemAt(e.X, e.Y);

            if ((e.X > listViewResults.Columns[0].Width) && (e.X < listViewResults.Columns[0].Width + listViewResults.Columns[1].Width))
            {
                if (lvi != null)
                {
                    if (lvi.SubItems[1].Text != "")
                    {
                        Rectangle ClickedItem = lvi.Bounds;

                        if ((ClickedItem.Left + listViewResults.Columns[1].Width) < 0)
                        {
                            return;
                        }

                        else if (ClickedItem.Left < 0)
                        {
                            if ((ClickedItem.Left + listViewResults.Columns[1].Width) > listViewResults.Width)
                            {
                                ClickedItem.Width = listViewResults.Width;
                                ClickedItem.X = listViewResults.Columns[0].Width;
                            }
                            else
                            {
                                ClickedItem.Width = listViewResults.Columns[1].Width + ClickedItem.Left;
                                ClickedItem.X = listViewResults.Columns[0].Width + 2;
                            }
                        }
                        else if (listViewResults.Columns[1].Width > listViewResults.Width)
                        {
                            ClickedItem.Width = listViewResults.Width;
                        }
                        else
                        {
                            ClickedItem.Width = listViewResults.Columns[1].Width;
                            ClickedItem.X = listViewResults.Columns[0].Width + 2;
                        }

                        ClickedItem.Y += listViewResults.Top;
                        ClickedItem.X += listViewResults.Left;

                        comboBoxMovie.Bounds = ClickedItem;

                        comboBoxMovie.Items.Clear();

                        MovieTag tag = (MovieTag)lvi.Tag;
                        foreach (TMDB.Movie movie in tag.Results)
                        {
                            if (movie.Released != null)
                            {
                                comboBoxMovie.Items.Add(movie.Name + " (" + movie.Released.Value.Year.ToString() + ")");
                            }
                            else
                            {
                                comboBoxMovie.Items.Add(movie.Name);
                            }
                        }
                        comboBoxMovie.SelectedIndex = 0;

                        comboBoxMovie.Visible = true;
                        comboBoxMovie.BringToFront();
                        comboBoxMovie.Focus();
                    }
                }
            }
        }
    }

    public struct MovieTag
    {
        public string Search;
        public TMDB.Movie[] Results;
        public Movie MovieInfo;
    }
}